package com.xcf.client;

import com.alibaba.fastjson.JSONObject;
import com.xcf.center.ServerMeta;
import com.xcf.center.client.ServerWrapper;
import com.xcf.model.RpcRequest;
import com.xcf.model.RpcResponse;
import io.netty.channel.*;

import java.util.concurrent.Callable;

public class UserClientHandler extends ChannelInboundHandlerAdapter implements Callable {

    private ServerWrapper<ServerMeta> serverWrapper;

    private ChannelHandlerContext context;
    private RpcResponse result;
    private Class<?> resultType;
    private RpcRequest request;

    public void setRequest(RpcRequest request) {
        this.request = request;
    }

    public void setResultType(Class<?> resultType) {
        this.resultType = resultType;
    }

    public void setServerWrapper(ServerWrapper<ServerMeta> serverWrapper) {
        this.serverWrapper = serverWrapper;
    }

    public void channelActive(ChannelHandlerContext ctx) {
        context = ctx;
    }

    @Override
    public synchronized void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("ctx = " + ctx);
        super.channelInactive(ctx);
        notify();
    }

    /**
     * 收到服务端数据，唤醒等待线程
     */

    public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) {
        result = (RpcResponse) msg;
        notify();
    }

    /**
     * 写出数据，开始等待唤醒
     */

    public synchronized Object call() throws Exception {
        long t1 = System.currentTimeMillis();
        serverWrapper.setLastRequestTime(t1);
        ChannelFuture channelFuture = context.writeAndFlush(request);
        UserClientHandler handler = this;
        channelFuture.addListeners(future -> {
            if (!future.isSuccess()) {
                synchronized (handler) {
                    notify();
                }
            }
        });
        wait();
        long t2 = System.currentTimeMillis();
        serverWrapper.setLastResponseTime(t2);
        serverWrapper.setLastHandlerTime(t2 - t1);
        if (null == result) {
            System.err.println("message code is error.");
            return null;
        }
        if (result.getSuccess()) {
            Object data = result.getData();
            if (resultType.isInstance(data)) {
                return data;
            }
            if (data instanceof JSONObject) {
                return ((JSONObject) data).toJavaObject(resultType);
            }
            return result.getData();
        }
        throw new RuntimeException(result.getException());
    }


}
